﻿using System;
using System.Collections.Generic;
using System.Threading;
using Wala.Connection.Argument;
using Wala.Connection.Constants;
using Wala.Common.Contact;
using Wala.Common.Chats;

namespace Wala.Connection.ComConnections
{
    public delegate void MessageTransferedEventHanler(Object sender, NotifyEventArgs notifyEventArgs);

    public class ConnectionManagement
    {
        private String ipAddress;

        private int port;

        public Object writeLock;
        public Object readLock;

        public Queue<DataTransfer> tranferQueue = new Queue<DataTransfer>(20);

        public Dictionary<long, SMS> ChatDictionary = new Dictionary<long, SMS>();

        private static ConnectionManagement instance;

        public enum ConnectionState { CONNECTED, DISCONNECTED, LOST_CONNECTION, CONNECTING };

        private ConnectionState state = ConnectionState.DISCONNECTED;

        private long messageId = 0;

        public event MessageTransferedEventHanler LoginMessageTransfered;

        public event MessageTransferedEventHanler MainViewMessageTransfered;

        NetworkChecker checker;

        private bool isReConnect=false;

        private CurrentContact currentContactObject = new CurrentContact();

        public bool GroupOfflineMsgDoneFlag=false;

        public bool LoadConversationDoneFlag = false;

        public CurrentContact CurrentContactObject
        {
            get { return currentContactObject; }
            set { currentContactObject = value; }
        }

        public bool IsReConnect
        {
            get { return isReConnect; }
            set { isReConnect = value; }
        }

        public long MessageId
        {
            get { return messageId; }
            set { messageId = value; }
        }

        public void IncreaseMessageId()
        {
            messageId++;
        }

        private ConnectionManagement() { }

        public static ConnectionManagement Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ConnectionManagement();
                }
                return ConnectionManagement.instance;
            }

        }

        public String IpAddress
        {
            get { return ipAddress; }
            set { ipAddress = value; }
        }

        public int Port
        {
            get { return port; }
            set { port = value; }
        }

        public ConnectionState State
        {
            get { return state; }
            set { state = value; }
        }

        public void write(byte[] data, int messageType)
        {
            if (tranferQueue == null)
            {
                tranferQueue = new Queue<DataTransfer>(20);
            }
            lock (writeLock)
            {
                DataTransfer dt = new DataTransfer();
                dt.Data = data;
                dt.MessageType = messageType;
                tranferQueue.Enqueue(dt);

                Monitor.Pulse(writeLock);
            }
        }

        public void NotifyUI(NotifyEventArgs notifyEventArgs)
        {
            switch (notifyEventArgs.Code)
            {
                case EventConstants.HAS_NETWORK:
                case EventConstants.RET_LOGIN_SUCCESS_MSG:
                case EventConstants.RET_LOGIN_ERROR_MSG:
                case EventConstants.RET_RECONNECT_SUCCESS_MSG:
                case EventConstants.RET_RECONNECT_ERROR_MSG:
                    if (LoginMessageTransfered != null)
                    {
                        LoginMessageTransfered(this, notifyEventArgs);
                    }
                    break;

                case EventConstants.CONNECT_FAIL:
                case EventConstants.RET_SOCKET_CONNECT_ERR:
                    tranferQueue.Clear();
                    //bool isAvailableNet = NetworkChecker.Check(URLConstant.GOOGLE_PING);
                    //if (!isAvailableNet)
                    //{
                    //    NetworkChecker.Host = URLConstant.GOOGLE_PING;
                    //}

                    StopSocket();
                    if (LoginMessageTransfered != null)
                    {
                        LoginMessageTransfered(this, notifyEventArgs);
                    }

                    if (IsReConnect)
                    {
                        State = ConnectionManagement.ConnectionState.LOST_CONNECTION;
                    }
                    else
                    {
                        State = ConnectionManagement.ConnectionState.DISCONNECTED;
                    }

                    break;

                case EventConstants.CANCEL_CONNECT:
                    if (LoginMessageTransfered != null)
                    {
                        LoginMessageTransfered(this, notifyEventArgs);
                    }
                    break;
                case EventConstants.RET_LOAD_PRESENCE_SUCCESS_MSG:
                case EventConstants.RET_LOAD_CONTACT:
                case EventConstants.RET_LOAD_BASIC_CONTACT:
                case EventConstants.LOG_OUT:
                case EventConstants.MULTIPLE_SIGN_IN_KICK:
                case EventConstants.LOAD_CONVERSATION_GROUP_DONE:
                case EventConstants.ADD_MORE_CONVERSATION_GROUP:
                    if (MainViewMessageTransfered != null)
                    {
                        MainViewMessageTransfered(this, notifyEventArgs);
                    }
                    break;
                case EventConstants.RET_LOST_CONNECTION:
                    StopSocket();
                    ConnectionManagement conn = ConnectionManagement.Instance;
                    conn.State = ConnectionManagement.ConnectionState.LOST_CONNECTION;
                    if (MainViewMessageTransfered != null)
                    {
                        MainViewMessageTransfered(this, notifyEventArgs);
                    }
                    
                    break;
            }
        }

        public void Start()
        {
            writeLock = new Object();
            readLock = new Object();
            checker = new NetworkChecker();
        }

        public void StopSocket()
        {
            //checker.StopSocket();
        }

        public void StartSocket()
        {
            //checker.StartSocket();
        }

        public void Close()
        {
            //if (checker != null && checker.Running == true)
            //{
            //    tranferQueue.Clear();
            //    checker.Close();
            //    State = ConnectionState.DISCONNECTED;
            //    isReConnect = false;
            //}
        }

        public void CloseAll()
        {
            //Thread thread = new Thread(new ThreadStart(Close));
            //thread.Start();
        }

        public void CancelConnect()
        {
            ConnectionManagement conn = ConnectionManagement.Instance;
            conn.NotifyUI(new NotifyEventArgs(EventConstants.CANCEL_CONNECT));
        }

        public void Logout()
        {
            //Thread thread = new Thread(new ThreadStart(Close));
            //thread.Start();

            ConnectionManagement conn = ConnectionManagement.Instance;
            conn.NotifyUI(new NotifyEventArgs(EventConstants.LOG_OUT));
        }

        public void PulseChecker()
        {
            //lock (checker.checkLock)
            //{
            //    Monitor.Pulse(checker.checkLock);
            //}
        }

        public void KickMultipleSignin()
        {
            //Thread thread = new Thread(new ThreadStart(Close));
            //thread.Start();

            ConnectionManagement conn = ConnectionManagement.Instance;
            conn.NotifyUI(new NotifyEventArgs(EventConstants.MULTIPLE_SIGN_IN_KICK));
        }
    }
}
